﻿using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BuddHa.Common.CryptoOpex
{
    public static class ASN1Helper
    {
        public static byte[] SM2ASN1toRS(byte[] asn1SM2RSValue)
        {
            try
            {
                Asn1Sequence sequence = Asn1Sequence.GetInstance(asn1SM2RSValue);
                DerInteger r = (DerInteger)sequence[0];
                DerInteger s = (DerInteger)sequence[1];
                byte[] r32Bytes = AsUnsigned32ByteArray(r.PositiveValue, 32);
                byte[] s32Bytes = AsUnsigned32ByteArray(s.PositiveValue, 32);
                byte[] sM2RS64Bytes = new byte[64];
                Array.Copy(r32Bytes, 0, sM2RS64Bytes, 0, 32);
                Array.Copy(s32Bytes, 0, sM2RS64Bytes, 32, 32);
                return sM2RS64Bytes;
            }
            catch (Exception ex)
            {
                throw new Exception("SM2ASN1toRS error: " + ex.Message, ex);
            }
        }

        public static byte[] AsUnsigned32ByteArray(BigInteger n, int length)
        {
            if (n == null)
            {
                return null;
            }
            else
            {
                byte[] tmp = new byte[length];
                byte[] arrays = n.ToByteArray();
                int len = arrays.Length;
                if (len > length + 1)
                {
                    return null;
                }
                else if (len == length + 1)
                {
                    if (arrays[0] != 0)
                    {
                        return null;
                    }
                    else
                    {
                        Array.Copy(arrays, 1, tmp, 0, length);
                        return tmp;
                    }
                }
                else
                {
                    Array.Copy(arrays, 0, tmp, length - len, len);
                    return tmp;
                }
            }
        }

        public static byte[] SM2RStoASN1(byte[] sign)
        {
            try
            {
                if (sign.Length != 32 * 2) throw new ArgumentException("err rs. ");
                BigInteger r = new BigInteger(1, Arrays.CopyOfRange(sign, 0, 32));
                BigInteger s = new BigInteger(1, Arrays.CopyOfRange(sign, 32, 32 * 2));
                Asn1EncodableVector rsV = new Asn1EncodableVector();
                rsV.Add(new DerInteger(r));
                rsV.Add(new DerInteger(s));
                return new DerSequence(rsV).GetEncoded("DER");
            }
            catch (Exception ex)
            {
                throw new Exception("SM2RStoASN1 error: " + ex.Message, ex);
            }
        }
    }
}
